package org.wisigoth.chat.client.jabber;

import java.util.HashMap;
import java.util.Iterator;

import org.wisigoth.chat.client.exceptions.WisigothRuntimeException;

public class InQueueThread extends Thread {

	private InPacketQueue packetQueue;

	public InQueueThread(InPacketQueue queue) {
		this.packetQueue = queue;
	}

	HashMap<PacketHandler, String> packetHandlers = new HashMap<PacketHandler, String>();

	public boolean addListener(PacketHandler listener, String element) {
		if (listener == null || element == null) {
			return false;
		}
		this.packetHandlers.put(listener, element);
		return true;
	}

	public boolean removeListener(PacketHandler listener) {
		this.packetHandlers.remove(listener);
		return true;
	}

	@Override
	public void run() {

		for (Packet packet = this.packetQueue.pull(); packet != null; packet = this.packetQueue
				.pull()) {

			try {
				if (packet.getFrom() == null) {
					packet.setFrom((packet.getSession()).whoAmI().toString());
				}
				String matchString = packet.getElement();

				synchronized (this.packetHandlers) {
					Iterator<PacketHandler> iter = this.packetHandlers.keySet()
							.iterator();
					boolean wasHandled = false;
					PacketHandler defaultListener = null;
					while (iter.hasNext()) {
						PacketHandler listener = iter.next();
						String listenerString = this.packetHandlers
								.get(listener);
						if (listenerString.length() == 0) {
							defaultListener = listener;
						} else if (listenerString.equals(matchString)) {
							listener.handle(packet);
							wasHandled = true;
						} // if
					} // while
					// Use the default listener (match string == "")
					// to handle any packets not handled by a regular
					// packet listener.
					if (!wasHandled && defaultListener != null) {
						defaultListener.handle(packet);
					}
				} // sync
			} catch (Exception ex) {
				throw new WisigothRuntimeException("QueueThread: ", ex);
			}
		} // for
	} // run()

	Packet waitFor(String element, String type) {
		for (Packet packet = this.packetQueue.pull(); packet != null; packet = this.packetQueue
				.pull()) {
			this.notifyHandlers(packet);
			if (packet.getElement().equals(element)) {
				if (type != null) {
					if (packet.getType().equals(type)) {
						return packet;
					}
				} else {
					return packet;
				}
			}
		}
		return null;
	}

	void notifyHandlers(Packet packet) {
		try {
			Packet child;
			String matchString;
			if (packet.getElement().equals("iq")) {
				child = packet.getFirstChild("query");
				if (child == null) {
					matchString = "iq";
				} else {
					matchString = child.getNamespace();
				}
			} else {
				matchString = packet.getElement();
			}

			synchronized (this.packetHandlers) {
				Iterator<PacketHandler> iter = this.packetHandlers.keySet()
						.iterator();
				while (iter.hasNext()) {
					PacketHandler listener = iter.next();
					String listenerString = this.packetHandlers.get(listener);
					if (listenerString.equals(matchString)) {
						listener.handle(packet);
					} // if
				} // while
			} // sync
		} catch (Exception ex) {
		}
	}
}

// } // class QueueThread
